Download OpenAPI specification:Download
Appendix D to the Technical Regulations of the Interaction Operator
Owner: Interaction Operator of CJSC'Demir Kyrgyz International Bank' (hereinafter DKIB)
The API description of interaction between Participants and Interaction Operators DKIB and other Interaction Operator.
This document provides the audience with OpenAPI specification for describing DKIB QR code collection's REST APIs. The scope of this document is limited to QR payments in Kyrgyzstan. The target audience of this document is the Developer, Business Analyst and other related Project Team Member of DKIB's client/ team (who has the basic technical know-how of Web technology such as REST or JSON).
There are two major API use cases throughout this document:
Interaction between DKIB and banks in its network
Interaction between the bank of the DKIB network and the bank of the other Operator network
In general, there will be 5 API requests during the transaction:
If the final status was not received at Execute process, the recipient Bank/PSP will have to send an update status request to the Interaction Operator, as soon as the transaction is processed, the Operator in its turn will redirect the update status request to the PSP sender, this is the end of the transaction process.
However, if the final status has not been received, the Sender PSP can send a status check request to the Operator, which in its turn makes the same request to the Beneficiary Bank/PSP.
When interacting between banks of the DKIB network, the interaction will be exclusively between three participants: the Sending bank (Payment Application), the Receiving bank (QR Acquiring) and the DKIB interaction operator.
API Interaction between DKIB and banks in its network
There will be 4 roles in the interaction between the banks of the DKIB network and the other Operator, the interaction operators will be intermediaries who redirect requests and responses to each other and/or to the relevant banks.
API Interaction between the bank of the DKIB network and the bank of the other Operator network
Case 1 - Sender is in DKIB Interaction Operator network and Receiver is in the IPC Interaction Operator network.
Case 2 - Sender is in IPC Interaction Operator network and Receiver is in the the DKIB Interaction Operator network.
These schemes work both ways, with the only difference in checking the status of the transaction, because the process of checking the status works differently in the systems of the two interaction operators. .
When two Banks-Members of different Interaction Operators interact, the requests and responses between the Receiving bank and the Sending bank will be the same as when two banks interact with one Operator, with the only difference being that now the requests and responses will not go through one Interaction Operator, but two.
In addition, on the side of the DKIB interaction operator there will be a request/response converter from the DKIB format to the IPC format and back.
Transaction statuses
| Status | Description | Final |
|---|---|---|
10 |
Created | No |
20 |
In process | No |
50 |
Success | Yes |
30 |
Error | Yes |
40 |
Canceled | Yes |
| Code | Type | Description |
|---|---|---|
| 10 | C2C | Transfer by QR code/payment link. |
| 20 | C2B | Purchase via QR code/payment link. |
| 30 | C2G | State payment (of an individual) by QR code/payment link. |
| 40 | B2C | Money transfer/withdrawal/refund by QR code/payment link. |
| 50 | B2B | Payment/transfer by QR code/payment link. |
| 60 | - | Electronic message on setting the reserve to the bank. |
| 70 | B2G | State payment (legal entity) by QR code/payment link. |
| Timeout type | Description | Time |
|---|---|---|
| Outgoing Execute Request | This timeout occurs , If the sender does not send an 'execute' request after receiving a 'create' response | 1 minute |
| Incoming Final Status | This timeout occurs in incoming QR, if our beneficiary doesn't send 'execute response' to the transaction wihtin the specified time after getting 'execute request' | 5 minutes |
| Http response | This timeout occurs when to http request of an Operator , participant doesn't resonse on time | 2 seconds |
To form a signature for POST requests, you must form a key pair (RSA 2048) - ReqPrivateKey ReqPublicKey and give ReqPublicKey to the project working group specialists in an encrypted archive.
If the header contains the signature version, by default it comes as H-SIGNING-VERSION = 1, but if the system uses the second version (described below) the header must contain H-SIGNING-VERSION = 2.
1) H-SIGNING-VERSION = 1
To form the header you need to form JWS of the sent payload request with and RSA private key. The signature is formed using ReqPrivateKey.
To from encrypted body you need to form JWE of the sent payload request with and RSA public key. The signature is formed using operator PublicKey.
Example code for generating signature and body:
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSADecrypter;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.EncryptedJWT;
import kg.ctechnology.api.psp.exception.AppException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.nio.file.Files;
import java.nio.file.Paths;
.....
public String signedPayload(String dtoJson, String privatePath) {
try{
String privateKey = new String(Files.readAllBytes(Paths.get(privatePath)));
RSAKey rsaJWK = (RSAKey) JWK.parseFromPEMEncodedObjects(privateKey);
JWSSigner signer = new RSASSASigner(rsaJWK);
JWSObject jwsObject = new JWSObject(
new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJWK.getKeyID()).build(),
new Payload(dtoJson));
jwsObject.sign(signer);
return jwsObject.serialize();
} catch (Exception e){
throw new AppException(e.getMessage());
}
}
public String encryptPayload(String dtoJson, String privatePath, String publicPath){
try {
String privateKey = new String(Files.readAllBytes(Paths.get(privatePath)));
String publicKey = new String(Files.readAllBytes(Paths.get(publicPath)));
RSAKey rsaJWK = (RSAKey) JWK.parseFromPEMEncodedObjects(privateKey);
RSAKey rsaPublicJWK = (RSAKey) JWK.parseFromPEMEncodedObjects(publicKey);
JWEEncrypter encrypter = new RSAEncrypter(rsaPublicJWK);
JWSObject jwsObject = new JWSObject(
new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJWK.getKeyID()).build(),
new Payload(dtoJson));
JWSSigner signer = new RSASSASigner(rsaJWK);
jwsObject.sign(signer);
JWEObject jweObject = new JWEObject(
new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM)
.contentType("JWT")
.build(),
new Payload(jwsObject));
jweObject.encrypt(encrypter);
return jweObject.serialize();
} catch (Exception ex){
throw new AppException(ex.getMessage());
}
}
2) H-SIGNING-VERSION = 2
The OPENSSL DGST SHA256 in base64 format will be used to sign requests.
import com.nimbusds.jose.*;
public String sign(String payload, String privatePath) {
try{
Signature signature = Signature.getInstance("SHA256withRSA");
String privateKeyFile = new String(Files.readAllBytes(Paths.get(privatePath)));
RSAKey rsaKey = (RSAKey) JWK.parseFromPEMEncodedObjects(privateKeyFile);
PrivateKey privateKey = rsaKey.toPrivateKey();
signature.initSign(privateKey);
signature.update(payload.getBytes(StandardCharsets.UTF_8));
byte[] signatureValue = signature.sign();
return Base64.encodeBase64String(signatureValue);
}catch (Exception e){
throw new AppException(e.getMessage());
}
}
public void verify(String payload, String sign, String publicPath) {
try{
Signature signature = Signature.getInstance("SHA256withRSA");
String publicKeyFile = new String(Files.readAllBytes(Paths.get(publicPath)));
RSAKey rsaKey = (RSAKey) JWK.parseFromPEMEncodedObjects(publicKeyFile);
PublicKey publicKey = rsaKey.toPublicKey();
signature.initVerify(publicKey);
byte[] data = payload.getBytes(StandardCharsets.UTF_8);
signature.update(data);
if(!signature.verify(Base64.decodeBase64(sign))){
throw new AccessDeniedException("Доступ к системе запрещен");
}
}catch (Exception e){
throw new AppException(e.getMessage());
}
}
It should be considered that the member banks interact exclusively with the Interaction Operator, i.e. all API requests/responses are received from the Interaction Operator, which in its turn processes all requests/responses and forms new requests/responses on their basis in order to forward them to another member bank.
It should also be noted that the scanning part must transfer all the content data in the acquirer's QR code, regardless of the mandatory nature of this field in the API queries.
Sender Bank/PSP sends requests to the Interaction Operator, and the Interaction Operator returns the response.
| qrVersion required | string Version of QR, by default "1", Field ID=00 from QR |
| H-PSP-TOKEN required | string Token for Payment system/ Sender Bank |
| H-PSP-ID required | string Payment system/ Sender bank indentificator |
| H-HASH required | string Signature of request |
| qrType required | string Enum: "staticQr" "dynamicQr" Payment link type, Field ID=01 from QR |
| merchantProvider required | string <= 32 Unique identificator of merchant provider, Field ID=32, SubID=00 from QR |
| merchantId | string <= 32 Service provider name, Field ID=59 from QR |
| serviceId | string <= 32 Service code in the Payment system, Field ID=32, SubID=01 from QR |
| serviceName | string <= 32 Service name in the Payment system, Field ID=33 SubID=01 from QR |
| beneficiaryAccountNumber | string <= 32 Unique identifier of the payer within the service (лицевой счет), Field ID=32, SubID=10 from QR |
| merchantCode required | integer <= 4 Service provider code (MCC), Field ID=52 from QR |
| currencyCode required | string <= 3 Currency, by default always "417", Field ID=53 from QR |
| qrTransactionId | string <= 32 Transaction ID, Field ID=32, SubID=11 from QR |
| qrComment | string <= 32 Comment for payment, Field ID=34 |
| customerType required | string Enum: 1 2 1 - Individual; 2 - Corp; Client type of sender, from system of Payment App/ Sender Bank |
| amount required | integer <= 13 Payment amount (in tyiyns), could be from QR or from Payment App/ Sender Bank |
| qrLinkHash required | string <= 4 Last 4 symbols of payment link hash string, Field ID=63 from QR |
Array of objects Additional fields for the sender, a maximum of 3 additional keys and values can be stored |
{- "qrType": "staticQr",
- "merchantProvider": "qr.demirbank.kg",
- "merchantId": "DKIB",
- "serviceId": "7001",
- "serviceName": "transfer",
- "beneficiaryAccountNumber": "11800000971044802",
- "merchantCode": 4829,
- "currencyCode": "417",
- "qrTransactionId": "1732832",
- "qrComment": "comment",
- "customerType": "1",
- "amount": 40000,
- "qrLinkHash": "67D9",
- "extra": [
- {
- "key": "...",
- "value": "..."
}
]
}{- "beneficiaryName": "c***e A***o",
- "transactionType": "10",
- "extra": [
- {
- "key": "...",
- "value": "..."
}
]
}| qrVersion required | string Version of QR, by default "1", Field ID=00 from QR |
| H-PSP-TOKEN required | string Token for Payment system/ Sender Bank |
| H-PSP-ID required | string Payment system/ Sender bank indentificator |
| H-HASH required | string Signature of request |
| qrType required | string Enum: "staticQr" "dynamicQr" Payment link type, Field ID=01 from QR |
| merchantProvider required | string <= 32 Unique identificator of merchant provider, Field ID=32, SubID=00 from QR |
| merchantId | string <= 32 Service provider name, Field ID=59 from QR |
| serviceId | string <= 32 Service code in the Payment system, Field ID=32, SubID=01 from QR |
| serviceName | string <= 32 Service name in the Payment system, Field ID=33 SubID=01 from QR |
| beneficiaryAccountNumber | string <= 32 Unique identifier of the payer within the service (лицевой счет), Field ID=32, SubID=10 from QR |
| merchantCode required | integer <= 4 Service provider code (MCC), Field ID=52 from QR |
| currencyCode required | string <= 3 Currency, by default always "417", Field ID=53 from QR |
| qrTransactionId | string <= 32 Transaction ID, Field ID=32, SubID=11 from QR |
| qrComment | string <= 32 Comment for payment, Field ID=34 |
| customerType required | string Enum: 1 2 1 - Individual; 2 - Corp; Client type of sender, from system of Payment App/ Sender Bank |
| pspTransactionId required | string <= 50 Transaction id by customer from the Sender's system |
| receiptId required | string <= 20 Sender's receipt number |
| amount required | integer <= 13 Payment amount (in tyiyns), could be from QR or from Payment App/ Sender Bank |
| qrLinkHash required | string <= 4 Last 4 symbols of payment link hash string, Field ID=63 from QR |
| transactionType required | string Enum: 10 20 30 40 50 60 70 Transaction type (specified in the table), Sender will get it from the IO when check requisites |
Array of objects Additional fields for the sender, a maximum of 3 additional keys and values can be stored |
{- "qrType": "staticQr",
- "merchantProvider": "qr.demirbank.kg",
- "merchantId": "DKIB",
- "serviceId": "7001",
- "serviceName": "transfer",
- "beneficiaryAccountNumber": "11800000971044802",
- "merchantCode": 4829,
- "currencyCode": "417",
- "qrTransactionId": "1732832",
- "qrComment": "comment",
- "amount": 40000,
- "qrLinkHash": "67D9",
- "customerType": "1",
- "pspTransactionId": "12512512341",
- "receiptId": "0924011",
- "transactionType": "10",
- "extra": [
- {
- "key": "...",
- "value": "..."
}
]
}{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 20,
- "transactionType": "10",
- "amount": 40000,
- "commission": 0,
- "senderTransactionId": "12512512341",
- "senderReceiptId": "0924011",
- "senderBic": "11800100",
- "beneficiaryBic": "11100100",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": "",
- "extra": [
- {
- "key": "...",
- "value": "..."
}
]
}| transactionId required | string Transaction ID from the Operator's system |
| H-PSP-TOKEN required | string Token for Payment system/ Sender Bank |
| H-PSP-ID required | string Payment system/ Sender bank indentificator |
| H-HASH required | string Signature of request |
{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 20,
- "transactionType": "10",
- "amount": 40000,
- "commission": 0,
- "senderTransactionId": "12512512341",
- "senderReceiptId": "0924011",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": "2022-11-01T12:01:00Z"
}The sender can send a status check request to the Interaction Operator. This request is for cases where, for whatever reason, the sender has not received the final status of the transaction (success/cancel).
| transactionId required | string Transaction ID from the Operator's system |
| H-PSP-TOKEN required | string Token for Payment system/ Sender Bank |
| H-PSP-ID required | string Payment system/ Sender bank indentificator |
{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 50,
- "transactionType": "10",
- "amount": 40000,
- "commission": 0,
- "senderTransactionId": "12512512341",
- "senderReceiptId": "0924011",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": "2022-11-01T12:01:00Z"
}Beneficiary Bank/PSP gets request from the Interaction Operator and responses with the related response API's.
| qrVersion required | string Version of QR, by default "1", Field ID=00 from QR |
| H-HASH required | string Signature of request |
| qrType required | string Enum: "staticQr" "dynamicQr" Payment link type, Field ID=01 from QR |
| merchantProvider required | string <= 32 Unique identificator of merchant provider (QR Acquirer), Field ID=32, SubID=00 from QR |
| merchantId | string <= 32 Service provider name, Field ID=59 from QR |
| serviceId | string <= 32 Service code in the Payment system of QR Acquirer, Field ID=32, SubID=01 from QR |
| serviceName | string <= 32 Service name in the Payment system, Field ID=33 SubID=01 from QR |
| beneficiaryAccountNumber | string <= 32 Unique identifier of the payer within the service (лицевой счет), Field ID=32, SubID=10 from QR |
| merchantCode required | integer <= 4 Service provider code (MCC), Field ID=52 from QR |
| currencyCode required | string <= 3 Currency, by default always "417", Field ID=53 from QR |
| qrTransactionId | string <= 32 Transaction ID in the QR Acquirer system, Field ID=32, SubID=11 from QR |
| qrComment | string <= 32 Comment for payment, Field ID=34 |
| amount required | integer <= 13 Payment amount (in tyiyns), could be from QR or from Payment App/ Sender Bank |
| qrLinkHash required | string <= 4 Last 4 symbols of payment link hash string, Field ID=63 from QR |
{- "qrType": "staticQr",
- "merchantProvider": "qr.demirbank.kg",
- "merchantId": "DKIB",
- "serviceId": "7001",
- "serviceName": "transfer",
- "beneficiaryAccountNumber": "11800000971044802",
- "merchantCode": 4829,
- "currencyCode": "417",
- "qrTransactionId": "1732832",
- "qrComment": "comment",
- "amount": 40000,
- "qrLinkHash": "67D9"
}{- "beneficiaryName": "c***e A***o",
- "customerType": "1"
}| qrVersion required | string Version of QR, by default "1", Field ID=00 from QR |
| H-HASH required | string Signature of request |
| transactionId required | string <uuid> Transaction ID from the Operator's system |
| amount required | integer <= 13 Payment amount (in tyiyns) |
| qrType required | string Enum: "staticQr" "dynamicQr" Payment link type, Field ID=01 from QR |
| merchantProvider required | string <= 32 Unique identificator of merchant provider, Field ID=32, SubID=00 from QR |
| merchantId | string <= 32 Service provider name, Field ID=59 from QR |
| serviceId | string <= 32 Service code in the Payment system, Field ID=32, SubID=01 from QR |
| serviceName | string <= 32 Service name in the Payment system, Field ID=33 SubID=01 from QR |
| beneficiaryAccountNumber | string <= 32 Unique identifier of the payer within the service (лицевой счет), Field ID=32, SubID=10 from QR |
| merchantCode required | integer <= 4 Service provider code (MCC), Field ID=52 from QR |
| currencyCode required | string <= 3 Currency, by default always "417", Field ID=53 from QR |
| qrTransactionId | string <= 32 Transaction ID from QR, Field ID=32, SubID=11 from QR |
| qrComment | string <= 32 Comment for payment, Field ID=34 |
| qrLinkHash required | string <= 4 Last 4 symbols of payment link hash string, Field ID=63 from QR |
| transactionType required | string Enum: 10 20 30 40 50 60 70 Transaction type (specified in the table) |
| senderTransactionId required | string <= 50 Transaction id from the Sender's system |
| senderReceiptId required | string <= 20 Sender's receipt number |
{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "amount": 40000,
- "qrType": "staticQr",
- "merchantProvider": "qr.demirbank.kg",
- "merchantId": "DKIB",
- "serviceId": "7001",
- "serviceName": "transfer",
- "beneficiaryAccountNumber": "11800000971044802",
- "merchantCode": 4829,
- "currencyCode": "417",
- "qrTransactionId": "1732832",
- "qrComment": "comment",
- "qrLinkHash": "67D9",
- "transactionType": "10",
- "senderTransactionId": "12512512341",
- "senderReceiptId": "0924011"
}{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 20,
- "transactionType": "10",
- "amount": 40000,
- "beneficiaryName": "c***e A***o",
- "customerType": "1",
- "receiptId": "7218199",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": ""
}| transactionId required | string Transaction ID from the Operator's system |
| H-HASH required | string Signature of request |
{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 20,
- "transactionType": "10",
- "amount": 40000,
- "beneficiaryName": "c***e A***o",
- "customerType": "1",
- "receiptId": "7218199",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": "2022-11-01T12:02:00Z"
}The Interaction Operator can send a status check request to the Beneficiary Bank/PSP. This request is for cases where, for whatever reason, the final status of the transaction has not been received (success/cancel/error).
| transactionId required | string Transaction ID from the Operator's system |
| H-HASH required | string Signature of request |
{- "transactionId": "fbded76a-9fc6-42d8-b0a0-e7e7110e0cc7",
- "status": 50,
- "transactionType": "10",
- "amount": 40000,
- "beneficiaryName": "c***e A***o",
- "customerType": "1",
- "receiptId": "7218199",
- "createdDate": "2022-11-01T12:00:00Z",
- "executedDate": "2022-11-01T12:02:00Z"
}During the 'Execute transaction' phase, if the Beneficiary does not return the final status, after the completion of the transaction, the Beneficiary will send an 'Update status' request to the 'Interaction Operator.' The received response will be forwarded to the 'Sender' by the 'Interaction Operator.' In addition, the 'Interaction Operator' may send an 'Update status' request to the Beneficiary or the Sender in case of a timeout. The method must be implemented on both the Operator's side and the Merchant's side.
| transactionId required | string Transaction ID from the Operator's system |
| H-PSP-TOKEN required | string Token for Payment system/ Sender Bank (for calling Operator API's) |
| H-PSP-ID required | string Payment system/ Sender bank indentificator (for calling Operator API's) |
| H-HASH required | string Signature of request |
| status required | integer Enum: 30 40 50 Transaction status (specified in the table), in this API only final status should be send |
| updateDate required | date-time Transaction status update date-time |
{- "status": 50,
- "updateDate": "2022-11-01T12:02:00Z"
}